package com.irdstudio.efp.edoc.service.impl.dw;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Vector;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.irdstudio.basic.framework.core.base.FrameworkService;
import com.irdstudio.basic.framework.core.constant.MonAlrmLvlEnums.MonAlrmLvlEnum;
import com.irdstudio.basic.framework.core.constant.StdZbHandleEnums.StdZbHandleEnum;
import com.irdstudio.basic.framework.core.exception.ESBException;
import com.irdstudio.basic.framework.core.util.DateTool;
import com.irdstudio.basic.framework.core.util.DateUtility;
import com.irdstudio.basic.framework.core.util.SFTPUtil;
import com.irdstudio.basic.framework.core.util.StringUtil;
import com.irdstudio.basic.framework.core.util.UUIDUtil;
import com.irdstudio.basic.framework.core.util.ZipUtil;
import com.irdstudio.efp.cus.service.facade.CusIndivService;
import com.irdstudio.efp.edoc.common.ImageBizConstant;
import com.irdstudio.efp.edoc.service.bo.ImageBizDetailVO;
import com.irdstudio.efp.edoc.service.bo.ImageBizInfoVO;
import com.irdstudio.efp.edoc.service.bo.LogErrorInfoVO;
import com.irdstudio.efp.edoc.service.bo.UpLoadFileVO;
import com.irdstudio.efp.edoc.service.facade.CfcaSignInfoService;
import com.irdstudio.efp.edoc.service.facade.ElectronicSignPolyService;
import com.irdstudio.efp.edoc.service.facade.ImageBizDetailService;
import com.irdstudio.efp.edoc.service.facade.ImageBizInfoService;
import com.irdstudio.efp.edoc.service.facade.ImageQueueTaskService;
import com.irdstudio.efp.edoc.service.facade.LogErrorInfoService;
import com.irdstudio.efp.edoc.service.facade.UpLoadFileService;
import com.irdstudio.efp.edoc.service.facade.dw.DwImageFileAnalysisService;
import com.irdstudio.efp.edoc.service.util.BaiduContractFileUtil;
import com.irdstudio.efp.esb.common.constant.ElectronicSignatureConstant;
import com.irdstudio.efp.esb.common.constant.ElectronicSignatureEnums;
import com.irdstudio.efp.esb.service.bo.req.dzqz.ReqElectronicSignature3001Bean;
import com.irdstudio.efp.esb.service.bo.req.dzqz.ReqElectronicSignature3203Bean;
import com.irdstudio.efp.esb.service.bo.req.dzqz.ReqElectronicSignatureDL01Bean;
import com.irdstudio.efp.esb.service.bo.req.dzqz.info.ElectronicSignature3001ReqPersonInfo;
import com.irdstudio.efp.esb.service.bo.req.dzqz.info.ElectronicSignature3203BaseInfo;
import com.irdstudio.efp.esb.service.bo.req.dzqz.info.ElectronicSignature3203SignInfo;
import com.irdstudio.efp.esb.service.bo.req.dzqz.info.ElectronicSignature3203SignKeyWord;
import com.irdstudio.efp.esb.service.bo.req.dzqz.info.ElectronicSignature3203SignPosnInfArry;
import com.irdstudio.efp.nls.common.constant.PrdInfoEnum;
import com.irdstudio.efp.nls.service.facade.BdLoanpayService;
import com.irdstudio.efp.nls.service.vo.BdLoanpayVO;
import com.jcraft.jsch.ChannelSftp;

/**
 * 
 * 存量百度借款协议解析
 * 
 * @author ludayong
 * @since 2019年6月5日 下午2:47:05
 * @version 1.0
 */
@Service("dwImageFileAnalysisService")
public class DwImageFileAnalysisServiceImpl implements DwImageFileAnalysisService, FrameworkService {

	private static Logger logger = LoggerFactory.getLogger(DwImageFileAnalysisServiceImpl.class);

	// 授权地址
	@Value("${gzcb.authaddr}")
	private String authaddr;

	// 合同名称
	@Value("${sign.baidu.contr_nm}")
	private String contrNm;

	// 签署关键字
	@Value("${sign.baidu.sign_kwd1}")
	private String signKwd1;

	// 签名域页数
	@Value("${sign.signonpgcnt}")
	private String signonpgcnt;

	// 签名域的左下角x轴坐标值
	@Value("${sign.signposnlbx}")
	private String signposnlbx;

	// 签名域的左下角y轴坐标值
	@Value("${sign.signposnlby}")
	private String signposnlby;

	// 签名域的右上角x轴坐标值
	@Value("${sign.signposnrux}")
	private String signposnrux;

	// 签名域的右上角y轴坐标值
	@Value("${sign.signposnruy}")
	private String signposnruy;

	// X轴偏移坐标
	@Value("${sign.baidu.xofstcoordposn}")
	private String xofstcoordposn;

	// Y轴偏移坐标
	@Value("${sign.baidu.yofstcoordposn}")
	private String yofstcoordposn;

	// 签章图片宽度
	@Value("${sign.signimgwdth}")
	private String signimgwdth;

	// 签章图片高度
	@Value("${sign.signimghght}")
	private String signimghght;

	// 存量百度借款协议下载路径
	@Value("${analysis.baiduTran.imageFileDownPath}")
	private String imageFileDownPath;

	// 存量百度借款协议解析路径
	@Value("${analysis.baiduTran.imageFilePath}")
	private String imageFilePath;

	// 存量百度借款协议归档路径
	@Value("${analysis.baiduTran.archImageFilePath}")
	private String archImageFilePath;

	// 存量百度借款协议本地备份路径
	@Value("${analysis.baiduTran.imageFileBakPath}")
	private String imageFileBakPath;

	// 存量百度借款协议下载最多个数
	@Value("${analysis.downNum}")
	private int downNum;

	// 前置文件服务器：存量百度借款协议下载地址
	@Value("${file.baiduTran.remoteImagesDownPath}")
	private String remoteImagesDownPath;

	// 前置文件服务器：存量百度借款协议备份地址
	@Value("${file.baiduTran.remoteImagesBakPath}")
	private String remoteImagesBakPath;

	// 前置文件服务器IP地址
	@Value("${ftp.host}")
	private String host;

	// 前置文件服务器用户名
	@Value("${ftp.username}")
	private String username;

	// 前置文件服务器登录密码
	@Value("${ftp.pwd}")
	private String pwd;

	// 前置文件服务器端口号
	@Value("${ftp.port}")
	private int port;

	// 百度存量百度借款协议压缩包后缀名
	@Value("${analysis.baidu.contract.tarGz}")
	private String tarGz;

	// 百度存量百度借款协议MD5后缀名
	@Value("${analysis.baidu.contract.md5}")
	private String md5;

	// 行方合同
	@Value("${analysis.baidu.contractOrgSuffix}")
	private String contractOrgSuffix;

	// 合作方合同
	@Value("${analysis.baidu.contractParSuffix}")
	private String contractParSuffix;

	// 影像业务信息
	@Autowired
	@Qualifier("imageBizInfoService")
	private ImageBizInfoService imageBizInfoService;

	// 影像业务文件
	@Autowired
	@Qualifier("imageBizDetailService")
	private ImageBizDetailService imageBizDetailService;

	// 影像任务队列
	@Autowired
	@Qualifier("imageQueueTaskService")
	private ImageQueueTaskService imageQueueTaskService;

	// 电子签章聚合服务
	@Autowired
	@Qualifier("dwElectronicSignPolyService")
	private ElectronicSignPolyService dwElectronicSignPolyService;

	// 客户中心
	@Autowired
	@Qualifier("cusIndivService")
	private CusIndivService cusIndivService;

	// CFCA签署信息
	@Autowired
	@Qualifier("cfcaSignInfoService")
	private CfcaSignInfoService cfcaSignInfoService;

	// 放款申请信息表
	@Autowired
	@Qualifier("bdLoanpayService")
	private BdLoanpayService bdLoanpayService;

	// 上传影像平台
	@Autowired
	@Qualifier("upLoadFileService")
	private UpLoadFileService upLoadFileService;

	// 异常信息表
	@Autowired
	@Qualifier("logErrorInfoService")
	private LogErrorInfoService logErrorInfoService;

	/**
	 * 
	 * 存量百度借款协议解析 <br>
	 * 0.1:ludayong:2019年6月5日 下午2:49:43:新增 <br>
	 * 
	 * @author ludayong
	 * @since 2019年6月5日 下午2:49:43
	 * @date 2019年6月5日 下午2:49:43
	 * @version 0.1
	 */
	@Override
	public synchronized boolean analysisImageFile() throws Exception {
		// 前置文件服务器下载文件
		boolean fileDownRes = downloadFile();
		long startTime = System.currentTimeMillis();
		logger.info("存量百度借款协议解析：[" + DateTool.formatDate(new Date(startTime), DateTool.PATTERN_DATETIME) + "]， 处理开始！");
		boolean result = false;
		boolean resultMYD = false;
		boolean resultZXD = false;
		// 要处理存量百度借款协议的产品代码
		String[] prdArrays = new String[] { PrdInfoEnum.MYD.getPrdId(), PrdInfoEnum.ZXD.getPrdId() };
		for (String prdCode : prdArrays) {
			String prdImageFilePath = imageFileDownPath + prdCode;
			// 1、解压存量百度借款协议
			File files = new File(prdImageFilePath);
			// 文件存在
			if (fileDownRes && files.exists()) {
				File[] imageFiles = files.listFiles();
				if (imageFiles.length > 0) {
					for (File imageFile : imageFiles) {
						if (imageFile.getName().endsWith(tarGz)) {
							// 流水号
							String applySeq = imageFile.getName().replace(tarGz, "") + "_" + prdCode;
							// 存量百度借款协议
							try {
								// MD5校验文件路径
								String md5FilePath = imageFile.getAbsolutePath().replace(tarGz, md5);
								File md5File = new File(md5FilePath);
								if (!md5File.exists()) {
									logger.error("tar包和MD5文件不在同一个文件夹下");
									throw new Exception("tar包和MD5文件不在同一个文件夹下");
								}
								// 1、解压存量百度借款协议
								BaiduContractFileUtil.doUnTarGZip(imageFile, md5File, tarGz);
								try {
									// 备份存量百度借款协议压缩包
									backupContractTarGZip(imageFile.getAbsolutePath(), imageFileBakPath, prdCode);
									// 备份存量百度借款协议md5校验文件
									backupContractTarGZip(md5FilePath, imageFileBakPath, prdCode);
									// 按订单号归类借款借据协议
									handleUnTarGZipImageFile(imageFile.getAbsolutePath().replace(tarGz, ""), prdCode);
									// 删除空文件夹
									removeContractEmpty(imageFile.getAbsolutePath().replace(tarGz, ""));
								} catch (Exception e) {
									String remark = "存量百度借款协议标准化解析出现异常，异常信息：" + e.getMessage();
									logger.error(remark);
									e.printStackTrace();
									// 记录异常信息
									recordLogErrorInfo(applySeq, remark, "", MonAlrmLvlEnum.SERIOUS.getEnname());
								}
							} catch (Exception e) {
								String remark = "存量百度借款协议解压出现异常，异常信息：" + e.getMessage();
								logger.error(remark);
								e.printStackTrace();
								// 记录异常信息
								recordLogErrorInfo(applySeq, remark, "", MonAlrmLvlEnum.SERIOUS.getEnname());
							}
						} else if (imageFile.isDirectory()) {
							// 流水号
							String applySeq = imageFile.getName() + "_" + prdCode;
							try {
								// 按订单号归类借款借据协议
								handleUnTarGZipImageFile(imageFile.getAbsolutePath(), prdCode);
								// 删除空文件夹
								removeContractEmpty(imageFile.getAbsolutePath().replace(tarGz, ""));
							} catch (Exception e) {
								String remark = "存量百度借款协议标准化解析出现异常，异常信息：" + e.getMessage();
								logger.error(remark);
								e.printStackTrace();
								// 记录异常信息
								recordLogErrorInfo(applySeq, remark, "", MonAlrmLvlEnum.SERIOUS.getEnname());
							}
						}
					}
				}
			}
			String prdImaFilePath = imageFilePath + prdCode;
			// 解析文件
			File imaFiles = new File(prdImaFilePath);
			// 文件存在
			if (imaFiles.exists()) {
				File[] imageFiles = imaFiles.listFiles();
				if (imageFiles.length > 0) {
					for (File imageFile : imageFiles) {
						if (imageFile.isDirectory()) {
							// 流水号
							String applySeq = imageFile.getName() + "_" + prdCode;
							try {
								// 存量百度借款协议签章
								result = this.handleAllImageFile(imageFilePath + prdCode, prdCode);
								if (PrdInfoEnum.MYD.getPrdId().equals(prdCode)) {
									resultMYD = result;
								} else if (PrdInfoEnum.ZXD.getPrdId().equals(prdCode)) {
									resultZXD = result;
								}
							} catch (Exception e) {
								String remark = "存量百度借款协议解析出现异常，异常信息：" + e.getMessage();
								logger.error(remark);
								e.printStackTrace();
								// 记录异常信息
								recordLogErrorInfo(applySeq, remark, "", MonAlrmLvlEnum.SERIOUS.getEnname());
							}
						}
					}
				}
			}
		}
		long endTime = System.currentTimeMillis();
		logger.info("存量百度借款协议解析：[" + DateTool.formatDate(new Date(endTime), DateTool.PATTERN_DATETIME) + "]， 处理结束！");
		logger.info("存量百度借款协议解析，耗时：[" + (endTime - startTime) / 1000.0 + "]秒！");
		return resultMYD || resultZXD;
	}

	/**
	 * 
	 * 存量百度借款协议标准化处理 <br>
	 * 0.1:ludayong:2019年4月9日 上午11:42:43:新增 <br>
	 * 
	 * @author ludayong
	 * @since 2019年3月22日 上午11:42:43
	 * @date 2019年3月22日 上午11:42:43
	 * @version 0.1
	 */
	private boolean handleUnTarGZipImageFile(String analysisPath, String prdCode) throws Exception {
		boolean reslut = false;
		// 1、存量百度借款协议个数
		int num = 0;
		File files = new File(analysisPath);
		File[] imageFiles = files.listFiles();
		// 处理状态
		List<String> states = new ArrayList<String>();
		states.add(StdZbHandleEnum.PENDING.getEnname());// 未处理
		states.add(StdZbHandleEnum.HANGING.getEnname());// 处理中
		if (imageFiles.length > 0) {
			for (File imgFile : imageFiles) {
				// 文件路径
				String imgFilePath = imgFile.getAbsolutePath();
				// 文件名
				String imgFileName = imgFile.getName();
				// 机构方存量百度借款协议
				if (imgFileName.endsWith(contractOrgSuffix)) {
					// 百度订单号
					String bdOrderId = imgFileName.replace(contractOrgSuffix, "");
					// 错误信息
					int errorNum = logErrorInfoService.countByApplySeqAndStates(bdOrderId, states);
					// 当前申请流水记录累计出现三次异常且未处理，不处理当前申请流水的存量百度借款协议
					if (errorNum >= 3) {
						// 不处理当前申请流水的存量百度借款协议
						continue;
					}
					// 借款协议存放路径
					String moveFilePath = imageFilePath + prdCode + File.separator + bdOrderId;
					boolean moveFileRes = ZipUtil.moveFile(imgFilePath, moveFilePath, imgFileName, true);
					logger.info("源路径：" + imgFilePath + "，目标路径：" + moveFilePath + "，结果[" + moveFileRes + "]");
					if (moveFileRes) {
						num++;
					}
					// 合作方存量百度借款协议文件路径
					String contractParFilePath = imgFilePath.replace(contractOrgSuffix, contractParSuffix);
					// 合作方存量百度借款协议文件
					File contractParFile = new File(contractParFilePath);
					if (contractParFile.exists()) {
						String parFileName = bdOrderId + contractParSuffix;
						boolean moveParFileRes = ZipUtil.moveFile(contractParFile.getAbsolutePath(), moveFilePath, parFileName, true);
						logger.info("源路径：" + imgFilePath + "，目标路径：" + moveFilePath + "，结果[" + moveParFileRes + "]");
					}
				} else if (imgFileName.endsWith(contractParSuffix)) {
					// 百度合作方借款协议
				} else {
					boolean removeFileRes = ZipUtil.deleteFile(imgFilePath);
					logger.info("清理未识别的存量百度借款协议，目标路径：" + imgFilePath + "，结果[" + removeFileRes + "]");
					continue;
				}
			}
		}
		if (num > 0) {
			reslut = true;
		}
		return reslut;
	}

	/**
	 * 
	 * 存量百度借款协议解析 <br>
	 * 0.1:ludayong:2019年4月9日 上午11:42:43:新增 <br>
	 * 
	 * @author ludayong
	 * @since 2019年3月22日 上午11:42:43
	 * @date 2019年3月22日 上午11:42:43
	 * @version 0.1
	 */
	private boolean handleAllImageFile(String analysisPath, String prdCode) throws Exception {
		boolean reslut = false;
		// 1、存量百度借款协议个数
		int handTotal = 0;
		File files = new File(analysisPath);
		File[] imageFiles = files.listFiles();
		// 处理状态
		List<String> states = new ArrayList<String>();
		states.add(StdZbHandleEnum.PENDING.getEnname());// 未处理
		states.add(StdZbHandleEnum.HANGING.getEnname());// 处理中

		if (imageFiles.length > 0) {
			for (File imgFile : imageFiles) {
				// 文件路径
				String imgFilePath = imgFile.getAbsolutePath();
				// 文件名
				String imgFileName = imgFile.getName();
				// 订单号
				String orderId = imgFileName;

				// 错误信息
				int errorNum = logErrorInfoService.countByApplySeqAndStates(orderId, states);
				// 当前申请流水记录累计出现三次异常且未处理，不处理当前申请流水的存量百度借款协议
				if (errorNum >= 3) {
					// 不处理当前申请流水的存量百度借款协议
					continue;
				} else if (handTotal >= downNum) {
					// 每次处理的文件个数
					break;
				}
				try {
					boolean handleImageFileRes = handleImageFile(imgFilePath, imgFileName);
					if (handleImageFileRes) {
						handTotal++;
					}
				} catch (Exception e) {
					String remark = "解析存量百度借款协议出现异常，异常信息：" + e.getMessage() + "，订单号：" + orderId;
					// 记录异常信息
					logger.error(remark);
					e.printStackTrace();
				}
			}
		}
		if (handTotal > 0) {
			reslut = true;
		}
		return reslut;
	}

	/**
	 * 
	 * 存量百度借款协议解析合同签章 <br>
	 * 0.1:ludayong:2019年4月9日 上午11:42:43:新增 <br>
	 * 
	 * @author ludayong
	 * @since 2019年3月22日 上午11:42:43
	 * @date 2019年3月22日 上午11:42:43
	 * @version 0.1
	 */
	private boolean handleImageFile(String filePath, String fileName) throws Exception {
		// 解析文件目录
		String analysisPath = filePath;
		String moveToPath = analysisPath.replace(imageFilePath, archImageFilePath);

		// 文件解析处理结果
		boolean reslut = false;
		// 电子签章处理结果
		boolean signReslut = false;
		// 新增/更新影像业务信息数据结果
		boolean addBizInfoRes = false;
		// 新增/更新影像业务文件数据结果
		boolean addBizDetaiRes = false;

		// 1、存量百度借款协议解析-校验存量百度借款协议个数
		// 订单号
		String orderId = fileName.replace(contractOrgSuffix, "");

		// 当前时间
		String currentTime = DateTool.getCurrentDateTime();
		Map<String, Object> param = new HashMap<String, Object>();

		// 放款明细信息
		BdLoanpayVO inBdLoanpayVO = new BdLoanpayVO();
		inBdLoanpayVO.setOrderId(orderId);
		// 查询放款明细信息
		BdLoanpayVO quertBdLoanpayVO = Optional.ofNullable(bdLoanpayService.queryByPk(inBdLoanpayVO)).orElseGet(BdLoanpayVO::new);
		param.put("bdLoanpayVO", quertBdLoanpayVO);

		// try {
		// // 放款明细信息不为空
		// Objects.requireNonNull(quertBdLoanpayVO);
		// param.put("bdLoanpayVO", quertBdLoanpayVO);
		// } catch (Exception e) {
		// String remark = "放款明细信息为空，订单号：" + orderId;
		// logger.error(remark);
		// e.printStackTrace();
		// // 记录异常信息
		// recordLogErrorInfo(orderId, remark, "bd_loanpay",
		// MonAlrmLvlEnum.SERIOUS.getEnname());
		// return false;
		// }

		ImageBizInfoVO imageBizInfoVO = new ImageBizInfoVO();// 影像业务信息
		// 订单号
		imageBizInfoVO.setApplySeq(orderId);
		// 产品id
		// TODO
		// imageBizInfoVO.setPrdId(quertBdLoanpayVO.getPrdId());
		// 产品代码
		// TODO
		// imageBizInfoVO.setPrdCode(quertBdLoanpayVO.getPrdCode());
		// 产品名称
		// TODO
		// imageBizInfoVO.setPrdName(quertBdLoanpayVO.getPrdName());
		// 客户号
		// TODO
		// imageBizInfoVO.setCusId(quertBdLoanpayVO.getCusId());
		// 客户名称
		imageBizInfoVO.setCusName(quertBdLoanpayVO.getCusName());
		// 存量百度借款协议接收
		imageBizInfoVO.setSoltImageAccept(ImageBizConstant.YesNoEnum.YES.VALUE);
		// 创建时间
		imageBizInfoVO.setCreateTime(currentTime);
		// 创建日期
		imageBizInfoVO.setCreateDate(DateTool.getCurrentDate());
		// 最近修改时间
		imageBizInfoVO.setLastModifyTime(currentTime);

		// 影像业务文件
		List<ImageBizDetailVO> imageBizDetailList = new ArrayList<ImageBizDetailVO>();
		// 上传影像平台
		List<UpLoadFileVO> upLoadFilelList = new ArrayList<UpLoadFileVO>();

		File files = new File(analysisPath);
		File[] imgFiles = files.listFiles();
		for (File imgFile : imgFiles) {
			// 文件路径
			String conFilePath = imgFile.getParent();
			// 文件路径
			String imageReaFilePath = imgFile.getAbsolutePath();
			imageReaFilePath = imageReaFilePath.replace(imageFilePath, archImageFilePath);
			String imageFileName = imgFile.getName();// 文件名

			// 去除订单号文件名
			String imgFileName = imageFileName.replace(orderId + "_", "");
			// 影像标识
			String imageId = imgFileName.indexOf(".") >= 0 ? imgFileName.substring(0, imgFileName.indexOf(".")) : "";

			// 影像业务文件
			ImageBizDetailVO imageBizDetailVO = new ImageBizDetailVO();
			// 订单号
			imageBizDetailVO.setApplySeq(orderId);
			// 影像标识
			imageBizDetailVO.setImageId(UUIDUtil.getUUID());

			// 上传影像平台信息
			UpLoadFileVO upLoadFileVO = new UpLoadFileVO();
			// 订单号
			upLoadFileVO.setApplySeq(orderId);
			// 上传文件路径
			upLoadFileVO.setFilePath(imageReaFilePath);
			// 流水号生成时间 yyyymmdd
			String currentDate = new SimpleDateFormat("yyyyMMdd").format(new Date());
			if (!StringUtil.isNullorBank(quertBdLoanpayVO.getApplyDate())) {
				currentDate = DateUtility.format10To8(quertBdLoanpayVO.getApplyDate());
			}
			upLoadFileVO.setStartDate(currentDate);// 流水号生成时间

			switch (imageId) {
			case ImageBizConstant.BD_FILE_SIGN_LOAN_PROTOCOL:
				// 影像类型
				imageBizDetailVO.setImageType(ImageBizConstant.IMAGE_TYPE_A05);
				// 文件描述
				imageBizDetailVO.setFileDesc(ImageBizConstant.FILE_SIGN_LOAN_PROTOCOL_DESC);
				// 影像类型
				upLoadFileVO.setImageType(ImageBizConstant.IMAGE_TYPE_A05);
				break;
			case ImageBizConstant.BD_FILE_SIGN_PARTNER_LOAN_PROTOCOL:
				// 影像类型
				imageBizDetailVO.setImageType(ImageBizConstant.IMAGE_TYPE_A09);
				// 文件描述
				imageBizDetailVO.setFileDesc(ImageBizConstant.BD_FILE_SIGN_PARTNER_LOAN_PROTOCOL_DESC);
				// 影像类型
				upLoadFileVO.setImageType(ImageBizConstant.IMAGE_TYPE_A09);
				break;
			default:
				boolean removeFileRes = ZipUtil.deleteFile(imgFile.getAbsolutePath());
				logger.info("清理未识别的存量百度借款协议，目标路径：" + imgFile.getAbsolutePath() + "，结果[" + removeFileRes + "]");
			}
			// 文件名
			imageBizDetailVO.setFileName(imageFileName);
			// 文件路径
			imageBizDetailVO.setFilePath(imageReaFilePath);
			// 创建时间
			imageBizDetailVO.setCreateTime(currentTime);
			// 最近修改时间
			imageBizDetailVO.setLastModifyTime(currentTime);
			// 创建时间
			upLoadFileVO.setCreateTime(currentTime);
			// 最近修改时间
			upLoadFileVO.setLastModifyTime(currentTime);

			// 存量百度借款协议
			imageBizDetailList.add(imageBizDetailVO);
			// 上传影像信息
			upLoadFilelList.add(upLoadFileVO);

			if (!StringUtil.isNullorBank(imageId) && imageId.equals(ImageBizConstant.BD_FILE_SIGN_LOAN_PROTOCOL)) {
				if (!imageFileName.endsWith(ImageBizConstant.LOAN_PROTOCOL_SUFFIX)) {
					String remark = "存量百度借款协议类型异常，请上传PDF格式存量百度借款协议！";
					logger.error(remark);
					// 记录异常信息
					recordLogErrorInfo(orderId, remark, "", MonAlrmLvlEnum.SERIOUS.getEnname());
					throw new Exception(remark);
				}

				// 3、合同签章
				param.put("orderId", orderId);
				param.put("tranCode", ElectronicSignatureConstant.TRAN_CODE_3203);
				param.put("opnFlg", ImageBizConstant.YesNoEnum.NO.VALUE);

				param.put("imageFilePath", imgFile.getAbsolutePath());// 存量百度借款协议路径
				param.put("conFilePath", conFilePath + File.separator);// 签章合同存放路径
				param.put("imageFileName", imageFileName);// 文件名

				try {
					param = this.initSignInfo(param);// 电子签章-签章信息初始化处理
				} catch (Exception e) {
					logger.error(e.getMessage());
					e.printStackTrace();
					// 记录异常信息
					recordLogErrorInfo(orderId, e.getMessage(), "", MonAlrmLvlEnum.SERIOUS.getEnname());
					throw new Exception(e.getMessage(), e);
				}

				try {
					// 电子签章-处理
					signReslut = dwElectronicSignPolyService.handleElectronicSignPoly(param);
					if (signReslut) {
						// 存量百度借款协议加签
						imageBizInfoVO.setSoltImageCfca(ImageBizConstant.YesNoEnum.YES.VALUE);
					} else {
						// 存量百度借款协议加签
						imageBizInfoVO.setSoltImageCfca(ImageBizConstant.YesNoEnum.NO.VALUE);
					}
				} catch (ESBException e) {
					// 存量百度借款协议加签
					imageBizInfoVO.setSoltImageCfca(ImageBizConstant.YesNoEnum.NO.VALUE);
					throw new Exception(e.getMessage(), e);
				}
			}
		}

		// 签章成功
		if (signReslut) {
			addBizInfoRes = addImageBizInfo(imageBizInfoVO);// 新增影像业务信息
			addBizDetaiRes = addImageBizDetail(imageBizDetailList);// 新增影像业务文件信息
		}
		if (addBizInfoRes && addBizDetaiRes) {// 百度借款协议解析后处理
			reslut = analysisAfterHandleFile(analysisPath, moveToPath, filePath);
		}
		return reslut;
	}

	/**
	 * 新增影像业务文件信息
	 * 
	 * @param imageBizDetailList
	 * 
	 * @return
	 * @author ludayong
	 * @since 2019年1月17日 下午8:40:42
	 * @version 1.0
	 */
	private boolean addImageBizDetail(List<ImageBizDetailVO> imageBizDetailList) {
		int bizDetaiNum = 0;// 新增/更新影像业务文件数据条数
		int listSize = 0;
		boolean reslut = false;
		logger.info("当前新增/更新影像业务文件数据为:" + JSONObject.toJSONString(imageBizDetailList));
		// 文件移动后新增/更新影像业务文件数据
		if (imageBizDetailList != null && !imageBizDetailList.isEmpty()) {
			for (ImageBizDetailVO imageBizDetailVO1 : imageBizDetailList) {
				listSize = imageBizDetailList.size();
				List<ImageBizDetailVO> queryImageBizDetailList = imageBizDetailService.queryByApplySeqAndImageType(imageBizDetailVO1);
				if (queryImageBizDetailList != null && !queryImageBizDetailList.isEmpty()) {
					bizDetaiNum += imageBizDetailService.updateByApplySeqAndImageType(imageBizDetailVO1);
				} else {
					bizDetaiNum += imageBizDetailService.insertImageBizDetail(imageBizDetailVO1);
				}
			}
		}
		logger.info("当前新增/更新影像业务文件数据条数为:" + bizDetaiNum);
		if (bizDetaiNum > 0 && bizDetaiNum == listSize) {
			reslut = true;
		}
		return reslut;
	}

	/**
	 * 新增影像业务信息
	 * 
	 * @param imageBizInfoVO
	 * 
	 * @return
	 * @author ludayong
	 * @since 2019年1月17日 下午8:40:42
	 * @version 1.0
	 */
	private boolean addImageBizInfo(ImageBizInfoVO imageBizInfoVO) {
		int bizInfoNum = 0;// 新增/更新影像业务信息数据条数
		boolean reslut = false;
		logger.info("当前新增/更新影像业务信息数据为:" + JSONObject.toJSONString(imageBizInfoVO));
		ImageBizInfoVO queryImageBizInfoVO = imageBizInfoService.queryByPk(imageBizInfoVO);
		if (queryImageBizInfoVO != null) {
			// 存量百度借款协议追加
			imageBizInfoVO.setSoltImageAccept("2");
			bizInfoNum = imageBizInfoService.updateByPk(imageBizInfoVO);
		} else {
			bizInfoNum = imageBizInfoService.insertImageBizInfo(imageBizInfoVO);
		}
		logger.info("当前新增/更新影像业务信息数据条数为:" + bizInfoNum);

		if (bizInfoNum > 0) {
			reslut = true;
		}
		return reslut;
	}

	/**
	 * 存量百度借款协议解析后文件处理
	 * 
	 * @param analysisPath
	 *            解析路径
	 * @param moveToPath
	 *            归档路径
	 * @param filePath
	 *            删除zip路径
	 * @return
	 * @author ludayong
	 * @since 2019年1月17日 下午8:40:42
	 * @version 1.0
	 */
	private boolean analysisAfterHandleFile(String analysisPath, String moveToPath, String filePath) {
		File srcDir = new File(analysisPath);
		if (srcDir.exists()) {// 文件存在
			File[] sourceFiles = srcDir.listFiles();
			if (sourceFiles.length > 0) {
				for (File sourceFile : sourceFiles) {
					if (sourceFile.isFile()) {
						File destFile = new File(moveToPath + File.separator + sourceFile.getName());
						if (destFile.exists()) {
							boolean removeFileRes = ZipUtil.deleteFile(destFile.getAbsolutePath());
							logger.info("目标文件存在，删除文件，目标路径：" + destFile.getAbsolutePath() + "，结果[" + removeFileRes + "]");
							boolean moveFileRes = ZipUtil.moveFile(sourceFile.getAbsolutePath(), destFile.getParent());
							logger.debug(
									"源路径：" + sourceFile.getAbsolutePath() + "，目标路径：" + destFile.getParent() + "，结果[" + moveFileRes + "]");
						} else {
							boolean moveFileRes = ZipUtil.moveFile(sourceFile.getAbsolutePath(), destFile.getParent());
							logger.debug(
									"源路径：" + sourceFile.getAbsolutePath() + "，目标路径：" + destFile.getParent() + "，结果[" + moveFileRes + "]");
						}
					}
				}
			}
		}
		File finallySrcPath = new File(analysisPath);
		File[] finallySrcFiles = finallySrcPath.listFiles();
		boolean removeFileRes = false;
		if (finallySrcFiles.length == 0) {
			removeFileRes = ZipUtil.deleteFolder(analysisPath);// 删除空目录
			logger.info("删除空目录，目标路径:" + analysisPath + "结果[" + removeFileRes + "]");
		}
		return removeFileRes;
	}

	/**
	 * 存量百度借款协议解析后文件处理
	 * 
	 * @param analysisPath
	 *            解析路径
	 * @param moveToPath
	 *            归档路径
	 * @param filePath
	 *            删除zip路径
	 * @return
	 * @author ludayong
	 * @since 2019年1月17日 下午8:40:42
	 * @version 1.0
	 */
	private boolean backupContractTarGZip(String filePath, String moveToPath, String prdCode) throws Exception {
		boolean moveFileRes = false;
		// 源文件
		File sourceFile = new File(filePath);
		// 目标路径
		String destFilePath = moveToPath + prdCode + File.separator + sourceFile.getName();
		// 目标文件
		File destFile = new File(destFilePath);
		if (destFile.exists()) {
			boolean removeFileRes = ZipUtil.deleteFile(destFile.getAbsolutePath());
			logger.info("目标文件存在，删除文件，目标路径：" + destFile.getAbsolutePath() + "，结果[" + removeFileRes + "]");
			moveFileRes = ZipUtil.moveFile(sourceFile.getAbsolutePath(), destFile.getParent());
			logger.debug("源路径：" + sourceFile.getAbsolutePath() + "，目标路径：" + destFile.getParent() + "，结果[" + moveFileRes + "]");
		} else {
			moveFileRes = ZipUtil.moveFile(sourceFile.getAbsolutePath(), destFile.getParent());
			logger.debug("源路径：" + sourceFile.getAbsolutePath() + "，目标路径：" + destFile.getParent() + "，结果[" + moveFileRes + "]");
		}
		return moveFileRes;
	}

	/**
	 * 存量百度借款协议解析后文件处理
	 * 
	 * @param analysisPath
	 *            解析路径
	 * @param moveToPath
	 *            归档路径
	 * @param filePath
	 *            删除zip路径
	 * @return
	 * @author ludayong
	 * @since 2019年1月17日 下午8:40:42
	 * @version 1.0
	 */
	private boolean removeContractEmpty(String analysisPath) throws Exception {
		boolean removeResult = false;
		File finallySrcPath = new File(analysisPath);
		File[] finallySrcFiles = finallySrcPath.listFiles();
		if (finallySrcFiles.length == 0) {
			removeResult = ZipUtil.deleteFolder(analysisPath);// 删除空目录
			logger.info("删除空目录，目标路径:" + analysisPath + "结果[" + removeResult + "]");
		}
		return removeResult;
	}

	/**
	 * 
	 * 电子签章-签章信息初始化处理<br>
	 * 
	 * @param param
	 * @return
	 * @date:2018年12月18日 下午3:35:05
	 * @author:ludayong
	 */
	private Map<String, Object> initSignInfo(Map<String, Object> param) throws ESBException, Exception {
		String tranCode = (String) param.get("tranCode");// 交易代码（接口代码）
		String opnFlg = (String) param.get("opnFlg");// 开户标识

		// 个人开户3001请求信息
		ReqElectronicSignature3001Bean req3001Bean = new ReqElectronicSignature3001Bean();
		// 上传合同3203请求信息
		ReqElectronicSignature3203Bean req3203Bean = new ReqElectronicSignature3203Bean();
		// 合同下载DL01请求信息
		ReqElectronicSignatureDL01Bean reqCADL01Bean = new ReqElectronicSignatureDL01Bean();

		// 放款申请信息
		BdLoanpayVO bdLoanpayVO = (BdLoanpayVO) param.get("bdLoanpayVO");

		// 需要开户
		if (ElectronicSignatureEnums.YesNoEnum.YES.VALUE.equals(opnFlg)) {
			ElectronicSignature3001ReqPersonInfo person = new ElectronicSignature3001ReqPersonInfo();
			// 客户名称
			person.setUsrNm(bdLoanpayVO.getCusName());
			person.setCertTp(bdLoanpayVO.getCertType());
			// 安心签会校验身份证格式
			person.setCertNo(bdLoanpayVO.getCertNo());
			// 邮箱与手机号不能同时为空；安心签会校验邮箱格式
			// person.setUserEmail("");
			// 邮箱与手机号不能同时为空；安心签会校验手机号格式
			// TODO
			// person.setMblNo("");
			// TODO
			// person.setCtcAddr("");// 联系地址
			// 客户平台与安心签协议中，明确的认证方式，例如：线下人工审核；公安部数据联网核查；绑定银行卡实名认证；其他（说明方式）
			person.setAuthMode(ElectronicSignatureConstant.AUTHENTICATION_MODE_02);

			req3001Bean.setPerson(person);
			// 0：发送；1：不发送；默认为0，建议选择发送
			req3001Bean.setSendPswdMsgFlg(ElectronicSignatureEnums.SendEnum.NotSend.VALUE);
			// 0：不校验；1：校验；默认为0
			req3001Bean.setVrfyBankCardInfFlg(ElectronicSignatureEnums.YesNoEnum.NO.VALUE);
		}

		if (ElectronicSignatureConstant.TRAN_CODE_3203.equals(tranCode)) {
			ElectronicSignature3203BaseInfo uploadContract = new ElectronicSignature3203BaseInfo();

			uploadContract.setSignFlg(ElectronicSignatureConstant.IS_SIGN_1);// 签署标志
			uploadContract.setContrTp(ElectronicSignatureConstant.CONTRACT_TYPE_CODE_JK);// 合同类型
			uploadContract.setContrNm(contrNm);// 合同名称

			ElectronicSignature3203SignKeyWord signKeyword = new ElectronicSignature3203SignKeyWord();
			signKeyword.setSignKwd(signKwd1); // 关键字
			signKeyword.setXOfstCoordPosn(xofstcoordposn); // X轴偏移坐标
			signKeyword.setYOfstCoordPosn(yofstcoordposn); // Y轴偏移坐标
			signKeyword.setSignImgWdth(signimgwdth); // 签章图片宽度
			signKeyword.setSignImgHght(signimghght); // 签章图片高度

			uploadContract.setSignKeyword(signKeyword);

			// **************************************************//
			List<ElectronicSignature3203SignPosnInfArry> signPosnInfArry = new ArrayList<ElectronicSignature3203SignPosnInfArry>();// 签名域签章信息
			ElectronicSignature3203SignPosnInfArry signLocation1 = new ElectronicSignature3203SignPosnInfArry();
			signLocation1.setSignOnPgCnt("1"); // 签名域页数
			signLocation1.setSignPosnLBX("85"); // 签名域的左下角X轴坐标值
			signLocation1.setSignPosnLBY("550"); // 签名域的左下角Y轴坐标值
			signLocation1.setSignPosnRUX("140"); // 签名域的右上角X轴坐标值
			signLocation1.setSignPosnRUY("575"); // 签名域的右上角Y轴坐标值

			signPosnInfArry.add(signLocation1);

			uploadContract.setSignPosnInfArry(signPosnInfArry);

			List<ElectronicSignature3203SignInfo> signInfos = new ArrayList<ElectronicSignature3203SignInfo>();// 签署信息
			ElectronicSignature3203SignInfo signInfo1 = new ElectronicSignature3203SignInfo();

			signInfo1.setUsrID(UUIDUtil.getUUID());// 用户ID
			signInfo1.setAuthTm(DateTool.getCurrentDateTimess());// 授权时间
			signInfo1.setAuthAddr(authaddr);// 授权地点
			signInfo1.setPrjNo(UUIDUtil.getUUID());// 项目编号
			signInfos.add(signInfo1);

			uploadContract.setSignBscInfArry(signInfos);
			// **************************************************//

			req3203Bean.setUploadContract(uploadContract);
		}
		param.put("req3001Bean", req3001Bean);
		param.put("req3203Bean", req3203Bean);
		param.put("reqCADL01Bean", reqCADL01Bean);
		return param;
	}

	/**
	 * 从前置文件服务器下载文件
	 * 
	 * @return
	 * @throws Exception
	 * @author ludayong
	 * @since 2019年1月15日 上午8:54:23
	 * @version 1.0
	 */
	private boolean downloadFile() throws Exception {
		long startTime = System.currentTimeMillis();
		logger.info("前置文件服务器获取文件：[" + DateTool.formatDate(new Date(startTime), DateTool.PATTERN_DATETIME) + "]， 处理开始！");
		// 连接前置文件服务器
		SFTPUtil sftpUtil = null;
		boolean fileDownRes = false;// 下载文件是否成功
		int downTotal = 0;
		List<String> states = new ArrayList<String>();
		states.add(StdZbHandleEnum.PENDING.getEnname());// 未处理
		states.add(StdZbHandleEnum.HANGING.getEnname());// 处理中

		try {
			// 要处理存量百度借款协议的产品代码
			String[] prdArrays = new String[] { PrdInfoEnum.MYD.getPrdId(), PrdInfoEnum.ZXD.getPrdId() };
			// 从前置文件服务器下载文件到本地
			sftpUtil = new SFTPUtil(username, pwd, host, port);
			for (String prdCode : prdArrays) {
				// 检测解析目录是否有需要解析的文件存在
				Vector<ChannelSftp.LsEntry> files = sftpUtil.ls(remoteImagesDownPath + prdCode);
				Objects.requireNonNull(files);// 文件不允许为空

				long handTime = System.currentTimeMillis() - 5 * 60 * 1000;
				for (ChannelSftp.LsEntry file : files) {
					String fileName = file.getFilename();// 下载文件名
					long fileMTime = file.getAttrs().getMTime() * 1000L;
					logger.info("处理时间[" + handTime + "]，文件最后修改时间[" + fileMTime + "]");
					if (".".equals(fileName) || "..".equals(fileName) || tarGz.equals(fileName)
							|| !(fileName.endsWith(tarGz) || fileName.endsWith(md5))) {
						continue;
					} else if (BaiduContractFileUtil.isMatchesCn(fileName)) {
						int num = logErrorInfoService.countByApplySeqAndStates(fileName, states);// 错误信息
						if (num < 3) {// 当前申请流水记录累计出现三次异常且未处理，不处理当前申请流水的存量百度借款协议
							String remark = "存量百度借款协议命名不规范（包含中文），请检查！";
							logger.error(remark);
							recordLogErrorInfo(fileName, remark, "", MonAlrmLvlEnum.WARNING.getEnname());
						}
						continue;
					} else if (downTotal >= downNum) {
						break;// 每次下载downNum个文件
					} else if (handTime > fileMTime) {// 前置文件服务器下载文件，文件在5分钟以前上传的
						try {
							String applySeq = "";
							if (fileName.endsWith(tarGz)) {
								applySeq = fileName.replace(tarGz, "");
							} else if (fileName.endsWith(md5)) {
								applySeq = fileName.replace(md5, "");
							}

							LogErrorInfoVO logErrorInfoVo = new LogErrorInfoVO();
							logErrorInfoVo.setApplySeq(applySeq);// 订单号
							logErrorInfoVo.setState(ElectronicSignatureEnums.YesNoEnum.NO.VALUE);// 未处理
							// int num = logErrorInfoService.countByApplySeq(logErrorInfoVo);// 错误信息
							int num = logErrorInfoService.countByApplySeqAndStates(applySeq, states);// 错误信息
							if (num >= 3) {// 当前申请流水记录累计出现三次异常且未处理，不处理当前申请流水的存量百度借款协议
								continue;// 不处理当前申请流水的存量百度借款协议
							}
							boolean singleFileDownRes = sftpUtil.downFile(sftpUtil, remoteImagesDownPath + prdCode + "/",
									file.getFilename(), imageFileDownPath + prdCode + File.separator, file.getFilename(), false);
							logger.info("前置文件服务器下载文件：" + remoteImagesDownPath + prdCode + File.separator + file.getFilename() + "，结果["
									+ singleFileDownRes + "]");
							if (singleFileDownRes) {
								downTotal++;// 下载文件数
								boolean renameReslut = renameFile(remoteImagesDownPath + prdCode + "/", fileName,
										remoteImagesBakPath + prdCode + "/");
								logger.info("前置文件服务器移动文件结果，目标路径：" + remoteImagesBakPath + fileName + "，结果[" + renameReslut + "]");
								if (!renameReslut) {
									String remark = "前置文件服务器移动文件出现异常";
									logger.error(remark);
									// 记录异常信息
									recordLogErrorInfo("", remark, "", MonAlrmLvlEnum.SERIOUS.getEnname());
								}
							}
						} catch (Exception e) {
							String remark = "前置文件服务器下载文件出现异常，异常信息：" + e.getMessage();
							e.printStackTrace();
							logger.error(remark);
							// 记录异常信息
							recordLogErrorInfo("", remark, "", MonAlrmLvlEnum.SERIOUS.getEnname());
						}
					}
				}
			}
			if (downTotal > 0) {// 下载文件数大于0，则解析
				fileDownRes = true;
			}
			logger.info("本次前置文件服务器下载文件数目：[" + downTotal + "]");
		} catch (Exception e) {
			String remark = "前置文件服务器下载文件出现异常，异常信息：" + e.getMessage();
			logger.error(remark + e.getMessage());
			e.printStackTrace();
			// 记录异常信息
			recordLogErrorInfo("", remark, "", MonAlrmLvlEnum.SERIOUS.getEnname());
		} finally {
			if (sftpUtil != null) {
				sftpUtil.closeSFTP();
			}
		}
		long endTime = System.currentTimeMillis();
		logger.info("前置文件服务器获取文件：[" + DateTool.formatDate(new Date(endTime), DateTool.PATTERN_DATETIME) + "]， 处理结束！");
		logger.info("前置文件服务器获取文件：，耗时：[" + (endTime - startTime) / 1000.0 + "]秒！");
		return fileDownRes;
	}

	/**
	 * 前置文件服务器移动文件
	 * 
	 * @param filePath
	 * @param fileName
	 * @return
	 * @throws Exception
	 * @author ludayong
	 * @since 2019年1月15日 上午9:23:42
	 * @version 1.0
	 */
	private boolean renameFile(String oldPath, String fileName, String newPath) {
		SFTPUtil sftpUtil = null;
		boolean renameRes = false;
		try {
			// 连接前置文件服务器
			sftpUtil = new SFTPUtil(username, pwd, host, port);
			// 从前置文件服务器移动目录
			renameRes = sftpUtil.renameFile(oldPath, fileName, newPath, true, true);
		} catch (Exception e) {
			String remark = "前置文件服务器移动文件出现异常，异常信息：" + e.getMessage();
			logger.error(remark + e.getMessage());
			e.printStackTrace();
			// 记录异常信息
			recordLogErrorInfo("", remark, "", MonAlrmLvlEnum.SERIOUS.getEnname());
		}
		return renameRes;
	}

	/**
	 * 记录异常信息
	 * 
	 * @param applySeq
	 * @param remark
	 * @param tableName
	 * @param errorType
	 * @return
	 * @throws Exception
	 * @author ludayong
	 * @since 2019年1月15日 上午9:23:42
	 * @version 1.0
	 */
	private void recordLogErrorInfo(String applySeq, String remark, String tableName, String errorType) {
		String currentTime = DateTool.getCurrentDateTime();// 当前时间
		// 错误信息
		LogErrorInfoVO logErrorInfoVo = new LogErrorInfoVO();
		logErrorInfoVo.setSerno(UUIDUtil.getUUID());// 主键
		logErrorInfoVo.setApplySeq(applySeq);
		logErrorInfoVo.setState(ElectronicSignatureEnums.YesNoEnum.NO.VALUE);// 未处理
		logErrorInfoVo.setCreateTime(currentTime);// 创建时间
		logErrorInfoVo.setLastModifyTime(currentTime);// 最后修改时间
		logErrorInfoVo.setTableName(tableName);// 表名
		logErrorInfoVo.setErrorMsg(remark);// 错误信息
		logErrorInfoVo.setRemark(remark);// 备注
		logErrorInfoVo.setErrorType(errorType);// 错误级别
		logErrorInfoService.insertLogErrorInfo(logErrorInfoVo);// 记录错误信息
	}
}
